package org.seedltd.upms.controller.miniapp;

import lombok.AllArgsConstructor;
import org.apache.commons.codec.binary.Base64;
import org.seedltd.core.base.BaseController;
import org.seedltd.core.utils.Assert;
import org.seedltd.core.utils.BeanUtils;
import org.seedltd.core.utils.StringUtils;
import org.seedltd.core.validation.Save;
import org.seedltd.log.LogAdapter;
import org.seedltd.log.annotation.SysLog;
import org.seedltd.springsecurity.utils.IPUtils;
import org.seedltd.springsecurity.utils.UserUtils;
import org.seedltd.upms.constant.GlobalConst;
import org.seedltd.upms.enums.OrderStatus;
import org.seedltd.upms.model.detection.dto.PayOrderDTO;
import org.seedltd.upms.model.detection.entity.DetectionOrder;
import org.seedltd.upms.model.detection.form.DetectionOrderBindingForm;
import org.seedltd.upms.model.detection.form.DetectionOrderDeliverForm;
import org.seedltd.upms.model.detection.vo.CreatePayOrderVO;
import org.seedltd.upms.model.detection.vo.DetectionMpConfigAPPVO;
import org.seedltd.upms.model.detection.vo.DetectionProductVO;
import org.seedltd.upms.model.detection.vo.QueryVO;
import org.seedltd.upms.model.sys.entity.SysUser;
import org.seedltd.upms.service.detection.DetectionMpConfigService;
import org.seedltd.upms.service.detection.DetectionOrderService;
import org.seedltd.upms.service.detection.DetectionProductService;
import org.seedltd.upms.service.detection.DetectionWeCharPayService;
import org.seedltd.upms.service.sys.SysUserService;
import org.seedltd.upms.utils.LocalLock;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 *
 * 小程序控制器
 *
 * @author laizuan
 * @version 1.0
 * @since 2021/8/12 15:14
 */
@RestController
@AllArgsConstructor
@RequestMapping("/mini-app/v1")
@PreAuthorize("hasRole('MINIAPPUSER')")
public class MiniAppController {
    protected final static LogAdapter logger = LogAdapter.getLogger(BaseController.class);

    private final DetectionOrderService detectionOrderService;
    private final DetectionWeCharPayService detectionWeCharPayService;
    private final SysUserService sysUserService;
    private final DetectionProductService detectionProductService;
    private final DetectionMpConfigService detectionMpConfigService;

    /**
     * 获取小程序配置
     * 
     * @return
     */
    @GetMapping(value = "/mpConfig")
    public DetectionMpConfigAPPVO getMpConfig() {
        Long companyId = UserUtils.getCompanyId();
        return BeanUtils.convert(detectionMpConfigService.findById(companyId), DetectionMpConfigAPPVO.class);
    }

    /**
     * 支付
     *
     * @param orderId
     *            订单主键
     */
    @SysLog("小程序订单支付")
    @GetMapping(value = "/pay/{orderId}")
    public CreatePayOrderVO doPay(@PathVariable Long orderId, HttpServletRequest request) throws Exception {
        DetectionOrder detectionOrder = detectionOrderService.getById(orderId);
        SysUser sysUser = sysUserService.findById(detectionOrder.getUserId());
        PayOrderDTO payOrderDTO = new PayOrderDTO();
        payOrderDTO.setDescription(detectionOrder.getProductNames());
        payOrderDTO.setOutTradeNo(detectionOrder.getTradeNo());
        payOrderDTO.setAmount(detectionOrder.getTotalPrice());
        payOrderDTO.setOpenid(sysUser.getWxOpenId());
        payOrderDTO.setClientIp(IPUtils.getIpAddr(request));
        CreatePayOrderVO createPayOrderVO = new CreatePayOrderVO();
        createPayOrderVO.setOrderId(orderId);
        createPayOrderVO.setPayPayment(detectionWeCharPayService.createOrder(payOrderDTO));
        return createPayOrderVO;
    }

    /**
     * 查询支付状态
     * 
     * @param orderId
     *            订单主键
     * @return
     * @throws Exception
     */
    @GetMapping(value = "/queryPayState/{orderId}")
    public boolean queryPayState(@PathVariable Long orderId) {
        DetectionOrder obj = detectionOrderService.getById(orderId);
        Assert.notNull(obj, "未找到已支付的订单");
        String tradeNo = obj.getTradeNo();
        try {
            LocalLock.lock(tradeNo);
            obj = detectionOrderService.getById(orderId);
            boolean isSuccess = false;
            if (obj.getState() < OrderStatus.UN_DELIVER.getValue()) {
                QueryVO query = detectionWeCharPayService.query(tradeNo);
                if (query.isSuccess()) {
                    isSuccess = true;
                    detectionOrderService.updatePayStatus(query, orderId);
                }
            }
            if (isSuccess && obj.getVendingMachineId() != null
                && GlobalConst.PURCHASE_CHANNEL_VM.equals(obj.getChannel())
                && GlobalConst.NO.equals(obj.getExportFlag())) {
                detectionOrderService.exportGoods(obj.getId(), false);
            }
            return isSuccess;
        } catch (Exception e) {
            logger.error(true, "支付完成查询支付状态处理异常：{}", e, e.getMessage());
            return false;
        } finally {
            LocalLock.unlock(tradeNo);
        }
    }

    /**
     * 获取产品列表
     * 
     * @return
     */
    @GetMapping(value = "/products")
    public List<DetectionProductVO> getProductList(Integer advertising) {
        return detectionProductService.listValid(advertising);
    }

    /**
     * 获取产品详情
     * 
     * @param productId
     *            产品主键
     * @return
     */
    @GetMapping(value = "/productDetail/{productId}", produces = "application/json;charset=UTF-8")
    public String getProductDetail(@PathVariable Long productId) {
        String detail = detectionProductService.getDetailByProductId(productId);
        if (StringUtils.isBlank(detail)) {
            return "";
        }
        return Base64.encodeBase64String(detail.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 绑定信息
     * 
     * @param form
     *            绑定数据
     * @return
     */
    @SysLog("小程序用户绑定信息")
    @PostMapping("/binding")
    public boolean binding(@RequestBody @Validated({Save.class}) DetectionOrderBindingForm form) {
        return detectionOrderService.binding(form);
    }

    /**
     * 检查二维码是否被绑定
     * 
     * @param orderId
     *            订单主键
     * @param qrcode
     *            二维码编号
     * @return 不为空标识正常
     */
    @GetMapping(value = "/check-binding/{orderId}/{qrcode}")
    public String checkBinding(@PathVariable Long orderId, @PathVariable String qrcode) {
        return detectionOrderService.checkBinding(orderId, qrcode);
    }

    /**
     * 投递样本
     * 
     * @param codeNo
     *            投递箱二维码编号
     * @param orderId
     *            订单主键
     * @return
     */
    @SysLog("小程序用户投递样本")
    @PostMapping("/deliver")
    public boolean deliver(Long orderId, String codeNo) {
        Assert.notNull(orderId, "订单主键不能为空，请返回上级页面重试");
        Assert.notNull(codeNo, "二维码编号不能为空，请重新扫描二维码");
        return detectionOrderService.deliver(orderId, codeNo);
    }

    /**
     * 批量投递样本
     * 
     * @param deliverForm
     *            投递数据对象
     * @return
     */
    @SysLog("小程序用户批量投递样本")
    @PostMapping("/delivers")
    public Integer delivers(@RequestBody @Validated DetectionOrderDeliverForm deliverForm) {
        String codeNo = deliverForm.getCodeNo();
        int flag = 1;
        for (Long orderId : deliverForm.getOrderIdList()) {
            try {
                detectionOrderService.deliver(orderId, codeNo);
            } catch (Exception e) {
                flag = 0;
            }
        }
        return flag;
    }

}
